﻿/**
 *	Copyright (c) 2009, SpLib.net
 * 	All rights reserved.
  	
 * 	Author:6spring
 * 	About:网络对象管理
*/

package org.dm.objSys
{
	import SpLib.Net.GLID;
	import SpLib.Net.GNID;
	import SpLib.Net.NetMsg;
	import SpLib.Tools.Tr;
	
	import com.pool.data.*;
	
	import org.dm.general.ClassGather;
	import org.dm.utils.Iterator;
	import org.dm.utils.List;
	import org.dm.utils.Map;
	import org.dm.utils.Queue;
		
	public class NetObjMgr
	{
		private static var _instance:NetObjMgr = null;
		private static var s_ObjSeed:int = 0;
		private static var s_WndID:int;
		
		private var m_szNetObj:Map;
		private var m_szRegObj:Map;
		private var m_szJoinObj:List = new List();
		private var m_szRecvPak:Queue = new Queue();
		private var m_nMaxProcMsgNum:int = 4096;
		
		public function NetObjMgr()
		{
			if(_instance!=null)
			{
				throw new Error("NetObjMgr is Singleton");
			}
			
			s_WndID = Math.random();
			m_szNetObj = new Map(GNID.compare);
			m_szRegObj = new Map(GOID.compare);
			
			//SpLib.Com.Com.AddUpdateFunc(OnProcTime);
		}
		
		public static function get Instance():NetObjMgr
		{
			var name:String = "org.dm.objSys.NetObjMgr";
			if(_instance==null)
			{
				_instance = ClassGather.tryClass(name, NetObjMgr);
			}
			return _instance;
		}
		
		public function SetMaxProcMsgNum(num:int):void
		{
			m_nMaxProcMsgNum = num;
		}
		
		public function AddJoin(gnid:GNID,thisobj:NetObjC):Boolean
		{
			var iter:Iterator = m_szJoinObj.first;
			while(iter!=null)
			{
				var obj:NetObjC = iter.data as NetObjC;
				if(obj.m_bDeled)
				{
					iter = m_szJoinObj.erase(iter);
				}
				else
				{
					if(obj.m_GNID.equal(gnid))
					{
						return false;
					}
					
					iter = iter.next;
				}
			}
			
			m_szJoinObj.push_back(thisobj);
			return true;
		}
		
		public function PopJoin(gnid:GNID):NetObjC
		{
			var iter:Iterator = m_szJoinObj.first;
			while(iter!=null)
			{
				var obj:NetObjC = iter.data as NetObjC;
				if(obj.m_bDeled)
				{
					iter = m_szJoinObj.erase(iter);
				}
				else
				{
					if(obj.m_GNID.equal(gnid))
					{
						m_szJoinObj.erase(iter);
						return obj;
					}
					
					iter = iter.next;
				}
			}
			
			return null;
		}
		
		public static function SendTo(glid:GLID,goid:GOID,evename:String,agv:Array):void
		{
			var msg:SpLib.Net.NetMsg = new SpLib.Net.NetMsg();
			msg.m_nMsgtype = SpLib.Net.NetMsg.TYPE_P2PDATA;
			
			msg.m_Address.m_nServiceID = glid.m_nIP;
			msg.m_Address.m_nGroupID = glid.m_nTypePort;
			msg.m_Address.m_nObjIDH = glid.m_nObjIDH;
			msg.m_Address.m_nObjIDL = glid.m_nObjIDL;
		
			msg.m_Value = new Array;
			msg.m_Value.push(goid.GetAsArray());
			msg.m_Value.push(agv);
			
			SpLib.Net.NetMsgMgr.SendMsg(msg);
		}
		
		public static function RegP2PObj(obj:BaseObj):GOID
		{
			var goid:GOID = new GOID();
			goid.m_nWndIDL = s_WndID;
			goid.m_nObjIDL = ++s_ObjSeed;
			Instance.m_szRegObj.insert(goid,obj);
			return goid;
		}
		
		public static function UnRegP2PObj(goid:GOID):void
		{
			Instance.m_szRegObj.remove(goid);
		}
		
		public static function FindP2PObj(goid:GOID):BaseObj
		{
			var iter:Iterator = Instance.m_szRegObj.find(goid);
			if(iter==null) return null;
			
			var obj:BaseObj = iter.data as BaseObj;
			if(obj.m_bDeled)
			{
				Instance.m_szRegObj.erase(iter);
				return null;
			}
			return obj;
		}
		
		public static function Add(gnid:GNID,obj:NetObjC):Boolean
		{
			return Instance.m_szNetObj.insert(gnid,obj);
		}
		
		public static function Find(gnid:GNID):NetObjC
		{
			var iter:Iterator = Instance.m_szNetObj.find(gnid);
			if(iter==null) return null;
			
			var obj:NetObjC = iter.data as NetObjC;
			if(obj.m_bDeled)
			{
				Instance.m_szNetObj.erase(iter);
				return null;
			}
			
			return obj;
		}
		
		public static function Del(gnid:GNID):void
		{
			Instance.m_szNetObj.remove(gnid);
		}
		
		public static function DelService(sid:int):void
		{
			var iter:Iterator = Instance.m_szNetObj.first;
			while(iter!=null)
			{
				var obj:NetObjC = iter.data as NetObjC;
				if(obj.m_bDeled)
				{
					iter = Instance.m_szNetObj.erase(iter);
				}
				else
				{
					if(obj.m_GNID.m_nServiceID==sid)
					{
						obj.ServiceBreak(sid);
						obj.DelObj();
						iter = Instance.m_szNetObj.erase(iter);
					}
					else
					{
						iter = iter.next;
					}
				}
			}
		}
		
		public function _DelGroup(sid:int,gid:int):void
		{
			var iter:Iterator = m_szNetObj.first;
			while(iter!=null)
			{
				var obj:NetObjC = iter.data as NetObjC;
				if(obj.m_bDeled)
				{
					iter = m_szNetObj.erase(iter);
				}
				else
				{
					if(obj.m_GNID.m_nServiceID==sid && obj.m_GNID.m_nGroupID==gid)
					{
						obj.DelObj();
						iter = m_szNetObj.erase(iter);
					}
					else
					{
						iter = iter.next;
					}
				}
			}
		}
		
		public static function DelGroup(sid:int,gid:int):void
		{
			Instance._DelGroup(sid,gid);
		}
		
		public static function Msg(msg:NetMsg):void
		{
			Instance.m_szRecvPak.push(msg);
			Instance.OnProcTime();
			
		}
		
		private function OnProcTime():void
		{
			var i:int;
			for(i=0;i<m_nMaxProcMsgNum;i++)
			{
				var msg:NetMsg = m_szRecvPak.pop() as NetMsg;
				if(msg==null)
					break;
				else
					ProcMsg(msg);
			}
		}
		
		private function ProcMsg(msg:NetMsg):void
		{
			trace(msg.m_nMsgtype+"--1---"+msg.m_Value[1]+"---2--"+msg.m_Value[2]+"---3--"+msg.m_Value[3]+"---4--"+msg.m_Value[4]);
			
			var netobj:NetObjC;
			var gnid:SpLib.Net.GNID;
			
			switch(msg.m_nMsgtype)
			{
				case NetMsg.TYPE_SESSION_SENDC:
					{
						netobj = Find(msg.m_Address);
						if(netobj!=null)
						{
							netobj.EventAsID(msg.m_nEveID,msg.m_Value);
						}
					}
					break;
				case NetMsg.TYPE_SESSION_JOIN_RESP:
					{
						if(msg.m_nEveID==1)
						{
							gnid = new SpLib.Net.GNID(msg.m_Value);
							
							netobj = Instance.PopJoin(msg.m_Address);
							if(netobj!=null)
							{
								Add(gnid,netobj);
								netobj.JoinGruopOk(msg.m_GLID,gnid);
							}
						}
						else
						{
							netobj = Instance.PopJoin(msg.m_Address);
							if(netobj!=null)
							{
								netobj.JoinGroupErr( msg.m_Value[0] as int, msg.m_Value[1] as String);
							}
						}
					}
					break;	
				case NetMsg.TYPE_MIRROR_CREATE:
					{
						var mainobj:NetObjC = Find(msg.m_Address);
						if(mainobj!=null)
						{
							var classname:String = msg.m_Value[0] as String;
							var result:Boolean=true;
							switch (classname) 
							{
								case "CGameDesk":
									RoomMgr.Instance.addRoomDesk(msg.m_Value);
									break;
								case "CRoomUser":
									result=UserDataMgr.Instance.add("room",msg.m_Value[1],[]);
									break;
								case "CDeskUser":
									result=UserDataMgr.Instance.add("room",msg.m_Value[1],[]);
									break;
								default:
									SpLib.Tools.Tr.Error("此对象" + classname + "不存在");
							}
							if(!result) SpLib.Tools.Tr.Error("创建对象" + classname + "失败");
						}
					}
					break;
				case NetMsg.TYPE_MIRROR_DESTROY:
					{
						netobj = Find(msg.m_Address);
						if(netobj!=null)
						{
							netobj.DelObj();
							Del(msg.m_Address);
						}
					}
					break;
				case NetMsg.TYPE_BREAKPLAYER:
					{
						netobj = Find(msg.m_Address);
						if(netobj!=null)
						{
							if(netobj.m_bIsMainPlayer)
							{
								netobj.BreakPlayer(msg.m_Value[0] as int,msg.m_Value[1] as String);
								netobj.DelObj();
								DelGroup(msg.m_Address.m_nServiceID,msg.m_Address.m_nGroupID);
							}
						}
					}
					break;
				case NetMsg.TYPE_SERVICEBREAK:
					{
						DelService(msg.m_Address.m_nServiceID);
					}
					break;
				case NetMsg.TYPE_P2PDATA:
					{
						var goid:GOID = new GOID(msg.m_Value[0] as Array);
						var p2pobj:BaseObj = FindP2PObj(goid);
						if(p2pobj!=null && p2pobj.m_bDeled)
						{
							p2pobj.EventAsID(msg.m_nEveID,msg.m_Value[1] as Array);
						}
					}
					break;
			}
		}
	}
}